/*  This file is part of the comicconquer project
    Copyright (C) 2010 Reach <reach334@gmail.com>

    ComicConquer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This software is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public 
    License along with this software.  If not, see <http://www.gnu.org/licenses/>.

*/


#include "QIplImage.h"

IplImage *QIplImage::QImageToIplImage(const QImage& image, int iscolor)
{
    if (iscolor == CV_LOAD_IMAGE_COLOR)
    {
        CvSize size = cvSize(image.width(), image.height());
        IplImage *pIplImage = cvCreateImage(size, IPL_DEPTH_8U, 3);

        int w = size.width;
        int h = size.height;
        uchar *data = (uchar *)pIplImage->imageData;
        int widthStep = pIplImage->widthStep;
        for (int y = 0; y < h; ++y)
        {
            for (int x = 0; x < w; ++x)
            {
                data[0] = qBlue(image.pixel(x, y));
                data[1] = qGreen(image.pixel(x, y));
                data[2] = qRed(image.pixel(x, y));

                data += 3;
            }
            data += (widthStep - 3*w);
        }

        return pIplImage;
    }
    else
    {
        CvSize size = cvSize(image.width(), image.height());
        IplImage *pIplImage = cvCreateImage(size, IPL_DEPTH_8U, 1);

        int w = size.width;
        int h = size.height;
        uchar* data = (uchar *)pIplImage->imageData;
        int widthStep = pIplImage->widthStep;

        for (int y = 0; y < h; ++y)
        {
            for (int x = 0; x < w; ++x)
            {
                *data = qGray(image.pixel(x, y));
                ++data;
            }

            data += (widthStep - w);
        }

        return pIplImage;
    }
}

QImage *QIplImage::IplImageToQImage(const IplImage *pIplImage, double min, double max)
{
    int width     = pIplImage->width;
    int height    = pIplImage->height;

    int widthStep = pIplImage->widthStep;

    QImage* qimage;

    switch (pIplImage->depth)
    {
    case IPL_DEPTH_8U:
        if (pIplImage->nChannels == 1)
        {
            QVector<QRgb> colorTable(256);

            for (int i = 0; i < colorTable.size(); i++)
            {
                colorTable[i] = qRgb(i, i, i);
            }

            qimage = new QImage(width, height, QImage::Format_Indexed8);
            qimage->setColorTable(colorTable);
            uchar* QImagePtr = qimage->bits();
            int bytesPerLine = qimage->bytesPerLine();
            const uchar *pIplImagePtr = (const uchar *) pIplImage->imageData;

            for (int y = 0; y < height; y++)
            {
                memcpy(QImagePtr, pIplImagePtr, width);

                QImagePtr += bytesPerLine;
                pIplImagePtr += widthStep;
            }
        }
        else if (pIplImage->nChannels == 3)
        {
            qimage = new QImage(width, height, QImage::Format_RGB32);
            uchar *QImagePtr = qimage->bits();
            const uchar *pIplImagePtr = (const uchar *) pIplImage->imageData;
            int bytesPerLine = qimage->bytesPerLine();

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    QImagePtr[0] = pIplImagePtr[0];
                    QImagePtr[1] = pIplImagePtr[1];
                    QImagePtr[2] = pIplImagePtr[2];
                    QImagePtr[3] = 0xff; 

                    QImagePtr += 4;
                    pIplImagePtr += 3;
                }

                QImagePtr += (bytesPerLine - 4*width);
                pIplImagePtr += (widthStep-3*width);
            }
        }
        else
        {
            qDebug("IplImageToQImage: image format is not supported : depth=8U and %d channels\n", pIplImage->nChannels);
            return NULL;
        }
        break;

    default:

        qDebug("pIplImageToQImage: image format is not supported : depth=%d and %d channels\n", pIplImage->depth, pIplImage->nChannels);
        return NULL;
    }

    return qimage;
} 

QImage* QIplImage::convertToGray(QImage* imgSrc, uchar transColor, bool isRetain)
{
    if (imgSrc == NULL) return NULL;

    switch (imgSrc->format())
    {
    case QImage::Format_Indexed8:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32:
    case QImage::Format_ARGB32_Premultiplied:
        {
            QImage* imgDst = new QImage(imgSrc->size(), QImage::Format_Indexed8);
            uchar* dataDst = imgDst->bits();
            int bytesPerLineDst = imgDst->bytesPerLine();
            int width = imgDst->width();
            int height = imgDst->height();

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    if (imgSrc->hasAlphaChannel() && qAlpha(imgSrc->pixel(x, y)) < 255)
                    {
                        *dataDst = transColor;
                    }
                    else
                    {
                        *dataDst = qGray(imgSrc->pixel(x, y));
                    }
                    ++dataDst;
                }
                dataDst += bytesPerLineDst - width;
            }

            if (!isRetain)
            {
                delete imgSrc;
                imgSrc = NULL;
            }

            QVector<QRgb> grayTable;
            for (int i = 0; i < 256; i++)
            {
                grayTable.append(qRgb(i, i, i)); 
            }
            imgDst->setColorTable(grayTable);
            return imgDst;
        }
        break;

    default:
        {
            return NULL;
        }
        break;
    }
}
